package com.ruiysoft.service.statement.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itopener.lock.redisson.spring.boot.autoconfigure.LockAction;
import com.itopener.lock.redisson.spring.boot.autoconfigure.LockType;
import com.ruiysoft.controller.wx.api.WeChatApi;
import com.ruiysoft.controller.wx.dto.DoTransferDto;
import com.ruiysoft.controller.wx.res.TransferredResponse;
import com.ruiysoft.entity.statement.StatementUser;
import com.ruiysoft.entity.statement.StatementUserDetail;
import com.ruiysoft.mapper.statement.StatementUserMapper;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.service.statement.IStatementUserDetailService;
import com.ruiysoft.service.statement.IStatementUserService;
import com.ruiysoft.service.statement.bean.StatementCondition;
import com.ruiysoft.service.statement.consts.StatementStatus;
import com.ruiysoft.service.statement.consts.StatementType;
import com.ruiysoft.util.TradeNoUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liyahui
 * @since 2018-12-01
 */
@Service
public class StatementUserServiceImpl extends ServiceImpl<StatementUserMapper, StatementUser> implements IStatementUserService {


    private static final Logger log = LoggerFactory.getLogger(StatementUserServiceImpl.class);
    @Resource
    private IStatementUserDetailService detailService;
    @Resource
    private WeChatApi weChatApi;

    @Override
    public Long selectSumMoney(StatementCondition condition) {
        return selectSumMoney(getWrapper(condition));
    }

    @Override
    @Transactional
    @LockAction(value = "#userId", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
    public void withdrawable(Long money, Long userId) {
        if (money <= 100) {
            throw new IllegalArgumentException("提现金额必须大于1元。");
        }
        Long withdrawable = selectSumMoney(new StatementCondition().setUserId(userId).setArrivalDateLast(new Date()).setFreeze(false));
        if (withdrawable > money) {
            throw new RuntimeException("提现金额超出可提现金额");
        }
        Date now = new Date();
        StatementUser statement = new StatementUser()
                .setTradeDate(now)
                //需要设置到账时间，不然可提现金额计算有问题
                .setArrivalDate(now)
                .setMoney(-money)
                .setSummary("个人提现")
                .setUserId(userId)
                .setTradeNo(TradeNoUtil.getTransactionNo())
                .setType(StatementType.expenditure.getIndex())
                .setFreeze(false);
        save(statement);
        StatementUserDetail detail = new StatementUserDetail()
                .setUserId(userId)
                .setStatus(StatementStatus.START.getIndex())
                .setStatementId(statement.getId())
                .setWorkDate(new Date());
        detailService.save(detail);
        expenditure(statement);
    }

    private void expenditure(StatementUser statement) {
        StatementUserDetail detail = new StatementUserDetail()
                .setUserId(statement.getUserId())
                .setStatus(StatementStatus.ON_THE_WAY.getIndex())
                .setStatementId(statement.getId())
                .setWorkDate(new Date());
        detailService.save(detail);

        Result<TransferredResponse> result = weChatApi.doTransfer(new DoTransferDto()
                .setAmount(new BigDecimal(-statement.getMoney()).multiply(new BigDecimal("0.994")).setScale(0, BigDecimal.ROUND_CEILING))
//                .setShopId(statement.getShopId())
                .setPersonnelId(statement.getUserId())
                .setTransactionNo(statement.getTradeNo()).setDesc("代收代付"));
        log.info("调用提现返回--{}", JSONObject.toJSON(result));
        if (!result.isSuccess()) {
            log.info("调用提现返回失败--{}", JSONObject.toJSON(result));
//            updateById(statement.setFreeze(true));
        } else {
            String voucherNo = result.getData() != null ? result.getData().getPaymentNo() : "";
            StatementUserDetail detail1 = new StatementUserDetail()
                    .setUserId(statement.getUserId())
                    .setStatus(StatementStatus.END.getIndex())
                    .setStatementId(statement.getId())
                    .setVoucherNo(voucherNo)
                    .setWorkDate(new Date());
            detailService.save(detail1);
        }
    }

    private Long selectSumMoney(QueryWrapper<StatementUser> wrapper) {
        Map<String, Object> map = getMap(wrapper.select("sum(money) sum"));
        return map != null && !map.isEmpty() ? ((BigDecimal) map.get("sum")).longValue() : 0;
    }

    private QueryWrapper<StatementUser> getWrapper(StatementCondition condition) {
        return new QueryWrapper<StatementUser>()
                .eq(condition.getShopId() != null, "shop_id", condition.getShopId())
                .eq(condition.getUserId() != null, "user_id", condition.getUserId())
                .eq(condition.getFreeze() != null, "is_freeze", condition.getFreeze())
                .eq(condition.getType() != null, "type", condition.getType() != null ? condition.getType().getIndex() : null)
                .lt(condition.getArrivalDateLast() != null, "arrival_date", condition.getArrivalDateLast())
                .orderBy(false, StringUtils.isNotBlank(condition.getOrderByClause()), condition.getOrderByClause());
    }
}
